package com.ilink.teacherservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ilink.ilinkapi.client.UserServiceClient;
import com.ilink.ilinkapi.dto.teacher.CrudCourseRequest;
import com.ilink.ilinkcommon.domain.PO.studyservice.*;
import com.ilink.ilinkcommon.domain.PO.trainingCamp.OfflineExport;
import com.ilink.ilinkcommon.domain.PO.trainingCamp.TrainingCamp;
import com.ilink.ilinkcommon.domain.PO.userService.UserProjectParticipation;
import com.ilink.ilinkcommon.domain.R;
import com.ilink.ilinkcommon.domain.User;
import com.ilink.ilinkcommon.domain.VO.UserAuthenticationResponse;
import com.ilink.ilinkcommon.service.oss.OssService;
import com.ilink.ilinkcommon.utils.BeanUtils;
import com.ilink.ilinkcommon.utils.SnowflakeIdGenerator;
import com.ilink.ilinkcommon.utils.UserContext;
import com.ilink.teacherservice.controller.videoTranscription.FileTranscriptionController;
import com.ilink.teacherservice.entity.DTO.CourseResponse;
import com.ilink.teacherservice.entity.DTO.StudyCourseFileResponse;
import com.ilink.teacherservice.entity.DTO.StudyResourceDto;
import com.ilink.teacherservice.entity.DTO.StudySourceFileResponse;
import com.ilink.teacherservice.entity.VO.CourserReviewResponse;
import com.ilink.teacherservice.entity.VO.TrainingCampListResponse;
import com.ilink.teacherservice.mapper.*;
import com.ilink.teacherservice.service.OfflineExportService;
import com.ilink.teacherservice.service.StudyTeacherCoursesTeacherService;
import com.ilink.teacherservice.service.StudyaboutTeacherService;
import com.ilink.teacherservice.service.bailian.FileService;
import com.ilink.teacherservice.service.videoTranscription.FileTranscriptionService;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import static com.ilink.ilinkcommon.domain.StatusEnum.COMPLETED;

@Transactional
@Service
@Slf4j
public class StudyaboutTeacherServiceImpl extends ServiceImpl<StudyTeacherCourseMapper, StudyTeacherCourse> implements
    StudyaboutTeacherService {

    //创建日志记录类实例
//    private static final log log = logFactory.getlog(StudyaboutTeacherServiceImpl.class);

    @Autowired
    private OssService ossService;
    @Autowired
    private StudyCourseFileMapper studyCourseFileMapper;
    @Autowired
    private StudyTeacherCourseMapper studyTeacherCourseMapper;
    @Autowired
    private CourseSourceMapper courseSourceMapper;
    @Autowired
    private StudyFileSourceMapper studyFileSourceMapper;
    @Autowired
    private StudyTeacherCoursesTeacherService studyTeacherCoursesTeacherService;
    @Autowired
    private StudyWebSourseMapper studyWebSourseMapper;
    @Autowired
    private  UserCourseStudyRecordMapper userCourseStudyRecordMapper;
    @Autowired
    private TrainingCampMapper trainingCampMapper;
    @Autowired
    private UserTrainingCampRecordMapper userTrainingCampRecordMapper;
    @Autowired
    private UserCourseStudyStatusMapper userCourseStudyStatusMapper;
    @Autowired
    private OfflineExportMapper offlineExportMapper;

    @Autowired
    private OfflineExportService offLineExportService;
    @Autowired
    private UserServiceClient userServiceClient;

    @Autowired
    FileService fileService;

    @Autowired
    private FileTranscriptionService fileTransService;
    @Autowired
    private FileTranscriptionController fileTranscriptionController;

    @Autowired
    private StudyResourceSortMapper studyResourceSortMapper;


    @Override
    public List<StudyResourceDto> getSortedResources(Long fieldId, String sentence) {
        return getSortedResources(fieldId, sentence, new HashSet<>());
    }

    private List<StudyResourceDto> getSortedResources(Long fieldId, String sentence, Set<Long> visitedFolders) {
        // 防止重复递归访问相同的文件夹，避免 StackOverflowError
        if (visitedFolders.contains(fieldId)) {
            return new ArrayList<>();
        }

        // 将当前文件夹标记为已访问
        visitedFolders.add(fieldId);

        // 获取与 fieldId 相关的文件夹和资源的排序信息
        List<StudyResourceSort> sortList = studyResourceSortMapper.selectList(
                new QueryWrapper<StudyResourceSort>()
                        .eq("file_id", fieldId)
                        .orderByAsc("sort_order")
        );

        List<StudyResourceDto> resourceList = new ArrayList<>();

        // 遍历排序列表，分别处理文件夹和资源
        for (StudyResourceSort sort : sortList) {

            if ("folder".equals(sort.getResourceType())) {
                // 使用 selectById 获取对应的文件夹
                StudyCourseFile courseFile = studyCourseFileMapper.selectById(sort.getResourceId());
                if (courseFile != null) {
                    // 创建新的 resource 对象
                    StudyResourceDto resource = new StudyResourceDto();
                    resource.setResourceId(courseFile.getCourseFileId());
                    resource.setName(courseFile.getName());
                    resource.setCreatedAt(courseFile.getCreatedAt());
                    resource.setResourcePath(courseFile.getFilePath());
                    resource.setTag("文件夹");
                    resource.setSortOrder(sort.getSortOrder());
                    resource.setIsFolder(true);
                    resource.setCourseId(courseFile.getCourseId());
                    resource.setLevel(courseFile.getLevel());

                    // 递归获取当前文件夹下的子文件夹和资源，并将其放入 childFiles
                    List<StudyResourceDto> childFiles = getSortedResources(courseFile.getCourseFileId(), sentence, visitedFolders);
                    if (!childFiles.isEmpty()) {
                        resource.setChildFiles(childFiles);
                    }

                    // 将该文件夹加入到资源列表
                    resourceList.add(resource);
                }
            } else {
                // 处理资源文档资源
                StudyFileSource studyFileSource = studyFileSourceMapper.selectById(sort.getResourceId());
                if (studyFileSource != null) {
                    // 创建新的 sourceDto 对象
                    StudyResourceDto sourceDto = new StudyResourceDto();

                    sourceDto.setResourceId(studyFileSource.getFilesourceId());
                    sourceDto.setName(studyFileSource.getFileName());
                    sourceDto.setCreatedAt(studyFileSource.getCreatedAt());
                    sourceDto.setResourcePath(studyFileSource.getFilesourcePath());
                    sourceDto.setTag("资源");
                    sourceDto.setSortOrder(sort.getSortOrder());
                    sourceDto.setIsFolder(false);
                    sourceDto.setCourseId(studyFileSource.getCourseId());
                    sourceDto.setHandleCompleteStatus(studyFileSource.getHandleCompleteStatus());
                    sourceDto.setOssWriteStatus(studyFileSource.getOssWriteStatus());
                    sourceDto.setRagCompleteStatus(studyFileSource.getRagCompleteStatus());
                    sourceDto.setSmartTextStatus(studyFileSource.getSmartTextStatus());

                    // 将资源添加到列表
                    resourceList.add(sourceDto);
                }

                // 获取音视频资源
                CourseSource courseSource = courseSourceMapper.selectById(sort.getResourceId());
                if (courseSource != null) {
                    // 创建新的 videoDto 对象
                    StudyResourceDto videoDto = new StudyResourceDto();

                    videoDto.setResourceId(courseSource.getCourseSourceId());
                    videoDto.setName(courseSource.getFileName());
                    videoDto.setCreatedAt(courseSource.getUpdatedAt());
                    videoDto.setResourcePath(courseSource.getFilesourcePath());
                    videoDto.setTag("音视频资源");
                    videoDto.setSortOrder(sort.getSortOrder());
                    videoDto.setIsFolder(false);
                    videoDto.setCourseId(courseSource.getCourseId());
                    videoDto.setTranscriptionComplete(courseSource.getTranscriptionComplete());
                    videoDto.setTranscriptionCompleteStatus(courseSource.getTranscriptionCompleteStatus());
                    videoDto.setOssWriteStatus(courseSource.getOssWriteStatus());

                    // 将音视频资源添加到列表
                    resourceList.add(videoDto);
                }

                // 获取网页资源
                StudyWebSourse webSourse = studyWebSourseMapper.selectById(sort.getResourceId());
                if (webSourse != null) {
                    // 创建新的 webDto 对象
                    StudyResourceDto webDto = new StudyResourceDto();

                    webDto.setResourceId(webSourse.getWebId());
                    webDto.setName(webSourse.getWebName());
                    webDto.setCreatedAt(webSourse.getUploadedAt());
                    webDto.setResourcePath(webSourse.getWebSoursePath());
                    webDto.setTag("网页资源");
                    webDto.setSortOrder(sort.getSortOrder());
                    webDto.setIsFolder(false);

                    // 将网页资源添加到列表
                    resourceList.add(webDto);
                }
            }
        }

        // 依据 sentence 对 Name 进行过滤
        if (sentence != null && !sentence.isEmpty()) {
            resourceList = resourceList.stream()
                    .filter(response -> response.getName().contains(sentence))
                    .collect(Collectors.toList());
        }

        // 返回排序后的资源列表
        return resourceList;
    }




    @Override
    public boolean newcreateChapter(String fileName, Long courseFileId, Integer sortOrder) throws Exception {
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);

        // 创建课程对应的文件夹
        StudyCourseFile courseFile = new StudyCourseFile();
        courseFile.setCourseFileId(idGenerator.nextId());
        courseFile.setName(fileName);

        // 根据 courseId 查询父文件夹的路径
        StudyCourseFile parent_file = studyCourseFileMapper.selectById(courseFileId);
        courseFile.setParentId(parent_file.getCourseFileId());
        String file_path = parent_file.getFilePath() + courseFile.getCourseFileId() + "/";
        courseFile.setFilePath(file_path);
        courseFile.setLevel(parent_file.getLevel() + 1);
        courseFile.setCourseId(parent_file.getCourseId());

        // 在前端传递的 sortOrder 基础上加 1
        int newSortOrder = sortOrder + 1;
        //courseFile.setSortOrder(newSortOrder);

        // 插入新章节到数据库
        studyCourseFileMapper.insert(courseFile);

        // 更新父文件夹, 增加层级关系
        parent_file.setChildId(courseFile.getCourseFileId());
        studyCourseFileMapper.updateById(parent_file);

        // 向RAG添加文件夹
        fileService.createCategory(parent_file.getFilePath(), courseFile.getCourseFileId() + "/");

        // 插入数据到study_resource_sort表
        StudyResourceSort studyResourceSort = new StudyResourceSort();
        studyResourceSort.setSortId(idGenerator.nextId()); // 使用雪花算法生成sortId
        studyResourceSort.setFileId(parent_file.getCourseFileId());
        studyResourceSort.setResourceId(courseFile.getCourseFileId());
        studyResourceSort.setResourceType("folder");
        studyResourceSort.setSortOrder(newSortOrder);

        // 插入新记录到study_resource_sort表
        studyResourceSortMapper.insert(studyResourceSort);

        // 向OSS添加文件夹
        return ossService.createDirectory(String.valueOf(courseFile.getCourseFileId()) + "/", parent_file.getFilePath());
    }



    @Transactional
    @Override
    public boolean createCourseWithFolder(String userid, CrudCourseRequest newTeacherCourse,
                                          List<MultipartFile> files) throws Exception {
        StudyTeacherCourse course = new StudyTeacherCourse();
//        StudyTeacherCoursesTeacher coursesTeacher = new StudyTeacherCoursesTeacher();

        //  雪花算法分配id
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
        course.setCourseId(idGenerator.nextId());
        course.setCourseName(newTeacherCourse.getCourseName());
        course.setCourseTag(newTeacherCourse.getCourseTag());
//        course.setCourseImage(newTeacherCourse.getCourseImage());
        course.setCourseDescription(newTeacherCourse.getCourseDescription());
        course.setViewNum(0L);
        course.setCreatedAt(new Date());

        // 创建课程对应的文件夹
        StudyCourseFile courseFile = new StudyCourseFile();
        courseFile.setCourseFileId(idGenerator.nextId());
        courseFile.setName(course.getCourseName());
        String file_path=userid+"/" + courseFile.getCourseFileId() +"/";
        courseFile.setFilePath(file_path);
        courseFile.setLevel(0);

        if (studyCourseFileMapper.insert(courseFile)>0){
            log.info("用户'{}'课程创建文件夹成功:{}",userid,courseFile);
        }else {
            log.error("用户'{}'课程创建文件夹失败:{}",userid,courseFile);
        }

        //写入课程基本信息
        // 获取刚刚创建的文件夹ID并设置到课程中
        course.setFolderId(courseFile.getCourseFileId());
        course.setTeacherId(userid);


        // 创建课程，继承了对应的表StudyTeacherCourse可以直接写入
        this.save(course);
        //由于外键关联得后续再加入
        courseFile.setCourseId(course.getCourseId());
        studyCourseFileMapper.updateById(courseFile);

        String filePath = userid + "/" + courseFile.getCourseFileId() + "/";
        // 处理文件上传到OSS
        if (files != null && !files.isEmpty()) {
            // 上传第一个文件作为 courseImage
            MultipartFile courseImageFile = files.get(0);
            String courseImageName = course.getCourseId() + getFileExtension(courseImageFile.getOriginalFilename());
            boolean courseImageUploadResult = ossService.uploadFile(courseImageFile, filePath, courseImageName);
            if (courseImageUploadResult) {
                course.setCourseImage(filePath + courseImageName);
            }

            // 上传剩余的文件作为每个 teacher 的 teacherImage
            List<StudyTeacherCoursesTeacher> teachers = newTeacherCourse.getTeacher();
            for (int i = 1; i < files.size(); i++) {
                MultipartFile teacherImageFile = files.get(i);
                StudyTeacherCoursesTeacher teacher = teachers.get(i - 1); // 第一个文件是 courseImage，从第二个文件开始对应 teacher
                // 保存教师信息到数据库
                teacher.setId(idGenerator.nextId());
                teacher.setCourseId(course.getCourseId());

                String teacherImageName = "teacher" + teacher.getId() + getFileExtension(teacherImageFile.getOriginalFilename());
                boolean teacherImageUploadResult = ossService.uploadFile(teacherImageFile, filePath, teacherImageName);
                if (teacherImageUploadResult) {
                    teacher.setTeacherImage(filePath + teacherImageName);
                }

                if (studyTeacherCoursesTeacherService.save(teacher)){
                    log.info("用户'{}'课程创建关联教师成功:{}",userid,teacher);
                }else {
                    log.error("用户'{}'课程创建关联教师失败:{}",userid,teacher);
                }
            }
        }

        // 更新课程表中的 courseImage
        if (course.getCourseImage() != null) {
            this.updateById(course);
        }
//        StudyTeacherCourse studyTeacherCourse = new StudyTeacherCourse();
//        studyTeacherCourse.setCourseId(idGenerator.nextId());
//        studyTeacherCourse.setTeacherId(userid);
//        studyTeacherCourse.setFolderId(courseFile.getCourseFileId());
//        studyTeacherCourse.setCourseName(course.getCourseName());
//        studyTeacherCour+se.setCourseDescription(course.getCourseDescription());
//        studyTeacherCourse.setCourseSchedule(course.getCourseSchedule());
//        studyTeacherCourse.setCourseTag(course.getCourseTag());
        //为用户账户创建用户路径
//        ossService.createDirectory(course.getTeacherId()+"/", "");
        //写入OSS String.valueOf(courseFile.getCourseFileId())
        //向RAG添加文件夹
        try {
            fileService.createCategory("", userid+"/");
        }
        catch (Exception e){
            System.out.println("RAG创建用户路径出错:"+e.getMessage());
        }
        System.out.println(userid+"/");
        System.out.println(course.getFolderId() +"/");

        fileService.createCategory(userid+"/", course.getFolderId() +"/");
        return ossService.createDirectory(course.getFolderId() +"/", userid+"/");
    }

    @Transactional
    @Override
    public boolean updateCourseById(String userId, Long courseId, CrudCourseRequest updatedTeacherCourse,
                                    List<MultipartFile> files){
        try{
            SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
            // 从数据库中查找要更新的课程
            StudyTeacherCourse existingCourse = studyTeacherCourseMapper.selectById(courseId);
            if (existingCourse == null) {
                log.error("课程不存在，无法更新，ID：" + courseId);
                return false;
            }

            // 更新课程的基本信息
            existingCourse.setCourseName(updatedTeacherCourse.getCourseName());
            existingCourse.setCourseTag(updatedTeacherCourse.getCourseTag());
            existingCourse.setCourseDescription(updatedTeacherCourse.getCourseDescription());
            existingCourse.setTeacherId(userId);
            existingCourse.setUpdatedAt(new Date()); // 假设有一个更新时间字段


            // 更新对应的文件夹名称
            StudyCourseFile courseFile = studyCourseFileMapper.selectById(existingCourse.getFolderId());
            if (courseFile != null) {
                courseFile.setName(updatedTeacherCourse.getCourseName());  // 使用新的课程名称作为文件夹名称
                studyCourseFileMapper.updateById(courseFile);  // 更新文件夹名称到数据库
            } else {
                log.error("无法找到课程对应的文件夹，ID：" + existingCourse.getFolderId());
                return false;
            }

            // 处理课程文件的路径
            String filePath = userId + "/" + existingCourse.getFolderId() + "/";

            // 更新文件到OSS，如果上传了新的文件
            if (files != null && !files.isEmpty()) {
                // 更新第一个文件作为 courseImage
                MultipartFile courseImageFile = files.get(0);
                String courseImageName = courseId + getFileExtension(courseImageFile.getOriginalFilename());
                boolean courseImageUploadResult = ossService.uploadFile(courseImageFile, filePath, courseImageName);
                if (courseImageUploadResult) {
                    existingCourse.setCourseImage(filePath + courseImageName);
                }

                // 首先根据 courseId 查询所有教师信息
                List<StudyTeacherCoursesTeacher> existingTeachers = studyTeacherCoursesTeacherService.list(
                        new LambdaQueryWrapper<StudyTeacherCoursesTeacher>()
                                .eq(StudyTeacherCoursesTeacher::getCourseId, courseId)
                );

                // 删除OSS中的旧教师图片文件
                for (StudyTeacherCoursesTeacher teacher : existingTeachers) {
                    if (teacher.getTeacherImage() != null) {
                        // 获取 teacherImage 字段存储的完整路径
                        String teacherImagePath = teacher.getTeacherImage();

                        // 提取路径和文件名
                        int lastSlashIndex = teacherImagePath.lastIndexOf('/');
                        if (lastSlashIndex != -1) {
                            String path = teacherImagePath.substring(0, lastSlashIndex + 1);  // 获取文件路径
                            String fileName = teacherImagePath.substring(lastSlashIndex + 1);  // 获取文件名
                            System.out.println("删除OSS中的教师图片");
                            System.out.println("path"+path);
                            System.out.println("fileName"+fileName);
                            boolean ossDeleteResult = ossService.deleteFile(fileName, path);
                            if (ossDeleteResult) {
                                log.info("成功删除OSS中的教师图片: {}", teacherImagePath);
                            } else {
                                log.error("删除OSS中的教师图片失败: {}", teacherImagePath);
                            }
                        } else {
                            log.error("无法解析教师图片路径: {}", teacherImagePath);
                        }
                    }
                }

                // 删除数据库中所有与 courseId 相关的教师信息
                studyTeacherCoursesTeacherService.remove(
                        new LambdaQueryWrapper<StudyTeacherCoursesTeacher>()
                                .eq(StudyTeacherCoursesTeacher::getCourseId, courseId)
                );

                // 重新上传新的教师信息
                List<StudyTeacherCoursesTeacher> teachers = updatedTeacherCourse.getTeacher();
                for (int i = 1; i < files.size(); i++) {
                    MultipartFile teacherImageFile = files.get(i);
                    StudyTeacherCoursesTeacher teacher = teachers.get(i - 1);  // 第一个文件是 courseImage，从第二个文件开始对应 teacher

                    // 新增教师信息，生成新的教师ID
                    teacher.setId(idGenerator.nextId());
                    teacher.setCourseId(courseId);

                    // 生成教师图片名称并上传到OSS
                    String teacherImageName = "teacher" + teacher.getId() + getFileExtension(teacherImageFile.getOriginalFilename());
                    boolean teacherImageUploadResult = ossService.uploadFile(teacherImageFile, filePath, teacherImageName);
                    if (teacherImageUploadResult) {
                        teacher.setTeacherImage(filePath + teacherImageName);
                    }

                    // 保存教师信息到数据库
                    if (studyTeacherCoursesTeacherService.save(teacher)) {
                        log.info("用户'{}'课程创建关联教师成功:{}", userId, teacher);
                    } else {
                        log.error("用户'{}'课程创建关联教师失败:{}", userId, teacher);
                    }
                }
            }

            // 更新课程信息到数据库
            studyTeacherCourseMapper.updateById(existingCourse);

            // 如果更新成功，返回 true
            return true;
        }catch (Exception e){
            log.error(e.getMessage());
            return false;
        }
    }

    // 获取文件后缀的方法
    private String getFileExtension(String fileName) {
        if (fileName == null) {
            return "";
        }
        int dotIndex = fileName.lastIndexOf('.');
        return dotIndex == -1 ? "" : fileName.substring(dotIndex);
    }


    //递归删除文件夹下对应的所有子文件夹和资源
    @Transactional
    @Override
    public boolean deleteCoursefileBycourseFile(Long courseFileId,Long courseId) throws Exception {
        // 删除课程对应的文件夹和层级资源，删除对应的OSS
        //直接删除父文档的ID即可，数据库自身会将子文件夹和资源关联删除  ON DELETE CASCADE
        //获取该文件夹
        StudyCourseFile courseFile = studyCourseFileMapper.selectById(courseFileId);
        if (courseFile != null) {
            //删除关联文件夹
            boolean deleteFolderResult = deleteSortfile(courseFileId);
            if (deleteFolderResult){
                log.info("成功删除文件夹排序关联数据{}",courseFileId);
            }else {
                log.error("删除文件夹{}排序关联数据失败",courseFileId);
            }

            //递归删除资源的转写，听悟
            //删除对应资源表，同时音视频资源表删除对应的关联转写
            deleteCourseFilesAndResources(courseFileId);
            //删除web对应资源

//          courseSourceMapper.delete(new QueryWrapper<CourseSource>().eq("course_id",courseId));
            //删除课程元信息中关联的文件夹
            if (courseFile.getLevel()<=0){
                if (studyTeacherCourseMapper.clearFolderIdByCourseId(courseId)>0){
                    log.info("成功解除课程{}与文件夹的关联",courseId);
                }else {
                    log.error("解除课程{}与文件夹的关联失败",courseId);
                }

            }
            //层级删除文件夹,其中排序的study_resource_sort表 中file_id有级联删除功能因此会一起删除了
            if (studyCourseFileMapper.deleteById(courseFileId)>0){
                log.info("成功递归删除文件夹{}",courseFileId);
            }else {
                log.error("递归" +
                        "删除文件夹{}失败",courseFileId);
            }

            // 课程文件夹，则最后删除课程，因为都与课程做了外键关联
            if (courseFile.getLevel()<=0){
//                this.removeById(courseId);//这一步有问题
                if ((studyTeacherCourseMapper.deleteById(courseId))>0){
                    log.info("成功注销课程{}",courseId);
                }else {
                    log.error("注销课程{}失败",courseId);
                }
//                    studyTeacherCourseMapper.delete(new QueryWrapper<StudyTeacherCourse>().eq("course_id",courseId));
            }
            //RAG上删除
            try {
                //TODO 加一个路径判断逻辑，rag里是否有
                R rag_result=fileService.deleteCategory(courseFile.getFilePath());
                if (rag_result.getCode()==200){
                    log.info("删除RAG文件夹{}时成功.",courseFile.getFilePath());
                }else{
                    log.error("删除RAG文件夹{}时失败，错误原因{}",courseFile.getFilePath(),rag_result.getData());
                }
            }
            catch (Exception e){
                log.error("删除RAG文件夹{}时发生异常，异常信息{}",courseFile.getFilePath(),e.getMessage());
            }
            // 删除文件夹
            try{
                //TODO 加一个路径判断逻辑，OSS里是否有
                if(ossService.deleteDirectory(courseFile.getFilePath())){
                    log.info("删除OSS文件夹{}时成功.",courseFile.getFilePath());
                }else{
                    log.error("删除OSS文件夹{}时失败",courseFile.getFilePath());
                }
            }
            catch (Exception e){
                log.error("删除OSS文件夹{}时发生异常，异常信息{}",courseFile.getFilePath(),e.getMessage());
            }

            return true;
        }
        return false;
    }


    // 递归删除课程文件夹及其关联数据
    @Transactional
    public void deleteCourseFilesAndResources(Long courseFileId) throws Exception {
        try {
            // 先删除当前文件夹的关联数据
            boolean relatedResourcesDeleted = deleteRelatedResources(courseFileId);
            if (relatedResourcesDeleted) {
                log.info("成功删除文件夹{}下的所有资源文件", courseFileId);
            } else {
                log.warn("删除文件夹{}下的所有资源文件失败", courseFileId);
            }

            // 获取当前文件夹的子文件夹ID
            List<StudyCourseFile> childFolderIds = studyCourseFileMapper.selectList(
                    new QueryWrapper<StudyCourseFile>().eq("parent_id", courseFileId)
            );


            // 递归删除子文件夹及其关联数据
            for (StudyCourseFile childFolderId : childFolderIds) {
                deleteCourseFilesAndResources(childFolderId.getCourseFileId());
                log.info("成功删除文件夹{}下资源 ", childFolderId.getName());
            }

            // 这里不需要删除当前文件夹，后续再递归删除
//            int deleteCount = studyCourseFileMapper.deleteById(courseFileId);
//            if (deleteCount > 0) {
//                log.info("成功删除文件夹{}", courseFileId);
//            } else {
//                log.warn("Failed to delete course file with courseFileId: {}", courseFileId);
//            }
//            //先删除当前文件夹的关联数据
//            deleteRelatedResources(courseFileId);
//
//            // 获取当前文件夹的子文件夹ID
//            List<StudyCourseFile> childFolderIds = studyCourseFileMapper.selectList(new QueryWrapper<StudyCourseFile>().eq("parent_id",courseFileId));
//
//
//            // 递归删除子文件夹及其关联数据
//            for (StudyCourseFile childFolderId : childFolderIds) {
//                deleteCourseFilesAndResources(childFolderId.getCourseFileId());
//            }
            // 删除当前文件夹
//        studyCourseFileMapper.deleteById(courseFileId);
        }
        catch (Exception e) {
            log.error("删除课程文件{}失败:, error={}", courseFileId, e.getMessage(), e);
            throw new Exception("删除课程文件及其关联资源时失败");

        }

    }

    // 删除当前文件夹的关联资源数据，add web
    @Transactional
    public Boolean deleteRelatedResources(Long courseFileId){
        try {
            // 初始化删除计数器
            int deleteCount = 0;
            List<Long> deleteIds = new ArrayList<>();
            //删除web
            deleteCount +=studyWebSourseMapper.delete(new QueryWrapper<StudyWebSourse>().eq("file_id",courseFileId));

            // 删除 coursesource 表中与当前文件夹相关的数据,音视频资源表删除对应的关联转写
    //        CourseSource courseSource=courseSourceMapper.selectOne()
            deleteCount +=courseSourceMapper.deleteCourseResourcesBycourseFileId(courseFileId);
            deleteCount +=courseSourceMapper.deleteCourseResourcesBycourseFileIdNoTask(courseFileId);
    //        courseSourceMapper.delete(new QueryWrapper<CourseSource>().eq("file_id",courseFileId));
            // 删除 study_filesource 表中与当前文件夹相关的数据
            deleteCount +=studyFileSourceMapper.delete(new QueryWrapper<StudyFileSource>().eq("file_id",courseFileId));

            //删除资源对应排序
            List<StudyWebSourse> webResources=studyWebSourseMapper.selectList(new LambdaQueryWrapper<StudyWebSourse>().eq(StudyWebSourse::getFileId,courseFileId));
            for(StudyWebSourse webResource:webResources){
                deleteIds.add(webResource.getWebId());
            }
            List<CourseSource> courseSources=courseSourceMapper.selectList(new LambdaQueryWrapper<CourseSource>().eq(CourseSource::getFileId,courseFileId));
            for(CourseSource courseSource:courseSources){
                deleteIds.add(courseSource.getCourseSourceId());
            }
            List<StudyFileSource> fileSources=studyFileSourceMapper.selectList(new LambdaQueryWrapper<StudyFileSource>().eq(StudyFileSource::getFileId,courseFileId));
            for(StudyFileSource fileSource:fileSources){
                deleteIds.add(fileSource.getFilesourceId());
            }
            if (!deleteIds.isEmpty()){
                // 使用 LambdaQueryWrapper 构造查询条件
                LambdaQueryWrapper<StudyResourceSort> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(StudyResourceSort::getResourceId, deleteIds);

                // 执行删除操作
                studyResourceSortMapper.delete(queryWrapper);
            }
            return deleteCount>=0;//删除成功

            }
        catch (Exception e) {
            log.error("删除课程文件夹关联{}所关联的资源时失败: error={}", courseFileId, e.getMessage(), e);
            throw new RuntimeException("删除课程文件对应资源时失败");
        }
    }


    //资源文件删除前的排序修改,不需要了会自动排序
//    public boolean updateSortOrderbydeleteSource(Long tragertId,Long parentId) throws Exception{
//
//        //获取资源的所在文件夹下的资源
//        List<StudyResourceSort> resourceandfolderList = studyResourceSortMapper.selectList(
//            new LambdaQueryWrapper<StudyResourceSort>()
//                .eq(StudyResourceSort::getFileId,parentId)
//        );
//        for (StudyResourceSort resourceandfolder : resourceandfolderList){
//
//        }
//
//        //搜索整个父文件夹下的排序
//
//
//
//        //更改在其后面的
//
//        //删除改文件于排序表
//    }
    //直接删除文件的排序关联
    public boolean deleteSortfile(Long tragertId) throws Exception {
        try {
            return studyResourceSortMapper.delete(new LambdaQueryWrapper<StudyResourceSort>().eq(StudyResourceSort::getResourceId,tragertId))>0;
        }
        catch (Exception e) {
            log.error("删除{}所排序关联时失败: error={}", tragertId, e.getMessage(), e);
            throw new Exception("删除排序关联时失败");
        }
    }
    @Override
    @Transactional
    public boolean deleteSourcesfile(Long sourceId, String type) throws Exception {
        if (type.equals("音视频资源")){
            CourseSource courseSource = courseSourceMapper.selectById(sourceId);
            String filePath = courseSource.getFilesourcePath();

            // 查找最后一个斜杠的位置
            int lastSlashIndex = filePath.lastIndexOf('/');

            // 使用substring方法进行拆分
            String directory = filePath.substring(0, lastSlashIndex + 1);
            String fileName = filePath.substring(lastSlashIndex + 1);
            if (courseSource != null) {
                if (courseSource.getOssWriteStatus()) {
                    //删除视频对应的OSS
                    if (ossService.deleteFile(fileName, directory)) {
                        log.info("OSS成功删除视频文件{}", courseSource.getFileName());
                    }else {
                        log.error("OSS删除视频文件{}失败", courseSource.getFileName());
                    }
                }

                if (courseSource.getTranscriptionComplete()) {
                    //删除视频对应的转写结果和音视频mysql元信息
                    if (courseSourceMapper.deleteCourseResourcesBySourCeId(sourceId)>0) {
                        log.info("MYSQL成功删除视频文件{}", courseSource.getFileName());
                    }else {
                        log.error("MYSQL删除视频文件{}失败", courseSource.getFileName());
                    }
                    //删除资源对应的sort关联
                    deleteSortfile(sourceId);
                    //RAG中删除
                    // 找到最后一个点的位置
                    int dotIndex = fileName.lastIndexOf('.');
                    // 如果文件名有扩展名，将其替换为 .txt
                    if (dotIndex != -1) {
                        fileName = fileName.substring(0, dotIndex) + ".txt";
                    } else {
                        // 如果没有扩展名，直接添加 .txt
                        fileName = fileName + ".txt";
                    }
                    R rag_result=fileService.deleteFile(directory, fileName);
                    if (rag_result.getCode()==1){
                        log.info("删除RAG文件夹{}时成功.",courseSource.getFileName());
                    }else{
                        log.error("删除RAG文件夹{}时失败，错误原因{}",courseSource.getFileName(),rag_result.getData());
                    }
                }else{
                    if (courseSourceMapper.deleteCourseResourcesBycourseSourceIdNoTask(sourceId)>0) {
                        log.info("MYSQL成功删除视频文件{}", courseSource.getFileName());
                    }else {
                        log.error("MYSQL删除视频文件{}失败", courseSource.getFileName());
                    }
                }

                return true;
            }
            else {
                return false;
            }
        }else if (type.equals("资源")){
            StudyFileSource studyCourseFile = studyFileSourceMapper.selectById(sourceId);
            if (studyCourseFile != null) {

            //删除MYsql中元信息
//            studyFileSourceMapper.delete(new QueryWrapper<StudyFileSource>().eq("filesource_id",sourceId));
            if (studyFileSourceMapper.delete(new QueryWrapper<StudyFileSource>().eq("filesource_id",sourceId))>0) {
                log.info("MYSQL成功删除文档文件{}", studyCourseFile.getFileName());
            }else {
                log.error("MYSQL删除文档文件{}失败", studyCourseFile.getFileName());
            }
            //删除资源对应的sort关联
            deleteSortfile(sourceId);
            String filePath =studyCourseFile.getFilesourcePath();
            // 查找最后一个斜杠的位置
            int lastSlashIndex = filePath.lastIndexOf('/');
            // 使用substring方法进行拆分
            String directory = filePath.substring(0, lastSlashIndex + 1);
            String fileName = filePath.substring(lastSlashIndex + 1);
            System.out.println(directory);
            System.out.println(fileName);
            //删除文档对应的OSS
            if (studyCourseFile.getOssWriteStatus()) {
//                ossService.deleteFile(fileName, directory);
                if (ossService.deleteFile(fileName, directory)) {
                    log.info("OSS成功删除文档文件{}", studyCourseFile.getFileName());
                }else {
                    log.error("OSS删除文档文件{}失败", studyCourseFile.getFileName());
                }
            }
            //RAG中删除
            if (studyCourseFile.getRagCompleteStatus()) {
                if (fileService.deleteFile(directory, fileName).getCode()==1){
                    log.info("删除RAG文档文件{}时成功.",studyCourseFile.getFileName());
                }else{
                    log.error("删除RAG文档文件{}时失败，错误原因{}",studyCourseFile.getFileName(),fileService.deleteFile(directory, fileName).getData());
                }
//                fileService.deleteFile(directory, fileName);
            }

            return true;

            } else {
                return false;
            }
        } else if (type.equals("网页资源")) {
            StudyWebSourse webSourse = studyWebSourseMapper.selectById(sourceId);
            if(webSourse != null){
                studyWebSourseMapper.deleteById(sourceId);
                //删除资源对应的sort关联
                deleteSortfile(sourceId);
                return true;
            }
            return false;
        }
        return false;
    }

    @Override
    public List<String> getCommonTags() { return studyTeacherCourseMapper.getCommonTags(); }


    @Override
    @Transactional
    public boolean deleteCourse(Long course_id) {
        // 删除课程对应的文件夹和层级资源，删除对应的OSS，删除课程的元信息表
        StudyTeacherCourse courseFile = studyTeacherCourseMapper.selectById(course_id);
        if (courseFile != null) {
            //删除文件夹,删除最大父文件夹，mysql自动关联删除所有的子文件夹
            int result=studyCourseFileMapper.deleteById(courseFile.getFolderId());
            if (result>0){
                // 删除OSS文件夹
                boolean deleteResult=ossService.deleteDirectory(courseFile.getTeacherId()+"/"+courseFile.getFolderId()+"/");
                if (!deleteResult){
                    return false;
                }
                //删除RAG文件夹


                // 最后删除课程元信息表StudyTeacherCourse，同时mysql自动删除对应的所有资源
                this.removeById(course_id);//删除对应的转写资源,资源文件已经关联了外键，所以删除课程时会自动关联删除
            }else{
                return false;
            }
            return true;
        }
        return false;
    }


    @Override
    public boolean createChapter(String fileName, Long courseFileId) throws Exception {
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
        // 创建课程对应的文件夹
        StudyCourseFile courseFile = new StudyCourseFile();
        courseFile.setCourseFileId(idGenerator.nextId());
        courseFile.setName(fileName);
        //根据courseId查询父文件夹的路径
        StudyCourseFile parent_file = studyCourseFileMapper.selectById(courseFileId);
        courseFile.setParentId(parent_file.getCourseFileId());
        String file_path=parent_file.getFilePath()+ courseFile.getCourseFileId() +"/";
        courseFile.setFilePath(file_path);
        courseFile.setLevel(parent_file.getLevel()+1);
        courseFile.setCourseId(parent_file.getCourseId());
        studyCourseFileMapper.insert(courseFile);

        //更新父文件夹,增加层级关系
        parent_file.setChildId(courseFile.getCourseFileId());
        studyCourseFileMapper.updateById(parent_file);

        //向RAG添加文件夹
        fileService.createCategory(parent_file.getFilePath(), courseFile.getCourseFileId() +"/");
        //向OSS添加文件夹
        return ossService.createDirectory(String.valueOf(courseFile.getCourseFileId())+"/", parent_file.getFilePath());

    }

    @Override
    public List<StudyCourseFileResponse> getCourseFiles(Long courseFileId, String sentence) {
        List<StudyResourceSort> sortList = studyResourceSortMapper.selectList(
                new QueryWrapper<StudyResourceSort>()
                        .eq("file_id", courseFileId)
                        .orderByAsc("sort_order")
        );

        List<StudyCourseFileResponse> responseList = new ArrayList<>();

        for (StudyResourceSort sort : sortList) {
            if (sort == null || sort.getResourceId() == null) {
                log.error("Sort or resourceId is null, skipping this entry.");
                continue;
            }

            if ("folder".equals(sort.getResourceType())) {
                List<StudyCourseFile> studyCourseFiles = studyCourseFileMapper.selectList(
                        new QueryWrapper<StudyCourseFile>().eq("parent_id", courseFileId).eq("courseFile_id", sort.getResourceId())
                );

                for (StudyCourseFile studyCourseFile : studyCourseFiles) {
                    StudyCourseFileResponse response = new StudyCourseFileResponse();
                    response.setCourseFileId(studyCourseFile.getCourseFileId());
                    response.setName(studyCourseFile.getName());
                    response.setCreatedAt(studyCourseFile.getCreatedAt());
                    response.setFilePath(studyCourseFile.getFilePath());
                    response.setLevel(studyCourseFile.getLevel());
                    response.setChildId(studyCourseFile.getChildId());
                    response.setParentId(studyCourseFile.getParentId());
                    response.setCourseId(studyCourseFile.getCourseId());
                    response.setSortOrder(sort.getSortOrder());

                    List<StudyCourseFileResponse> childFiles = getCourseFiles(studyCourseFile.getCourseFileId(), sentence);
                    response.setChildFiles(childFiles);

                    List<StudySourceFileResponse> studySourceFileResponses = getSourseFiles(studyCourseFile.getCourseFileId(), sentence);

                    List<StudyWebSourse> webSourses = studyWebSourseMapper.getWebByCourseFileId(studyCourseFile.getCourseFileId());
                    List<StudySourceFileResponse> webSourceFiles = webSourses.stream()
                            .map(webSourse -> {
                                StudySourceFileResponse webResponse = new StudySourceFileResponse();
                                webResponse.setSourceId(webSourse.getWebId());
                                webResponse.setName(webSourse.getWebName());
                                webResponse.setSourcePath(webSourse.getWebSoursePath());
                                webResponse.setCreatedAt(webSourse.getUploadedAt());
                                webResponse.setTag("网页资源");

                                StudyResourceSort webSort = sortList.stream()
                                        .filter(s -> s != null && s.getResourceId() != null && s.getResourceId().equals(webSourse.getWebId()) && "web".equals(s.getResourceType()))
                                        .findFirst()
                                        .orElse(null);

                                webResponse.setSortOrder(webSort != null ? webSort.getSortOrder() : 0);
                                return webResponse;
                            }).collect(Collectors.toList());

                    List<StudySourceFileResponse> allSourceFiles = new ArrayList<>();
                    allSourceFiles.addAll(studySourceFileResponses);
                    allSourceFiles.addAll(webSourceFiles);

                    allSourceFiles.sort(Comparator.comparingInt(file -> file.getSortOrder() != null ? file.getSortOrder() : 0));
                    response.setSourceFiles(allSourceFiles);

                    responseList.add(response);
                }
            } else {
                List<StudySourceFileResponse> studySourceFileResponses = getSourseFiles(sort.getFileId(), sentence);

                for (StudySourceFileResponse studySourceFileResponse : studySourceFileResponses) {
                    if (studySourceFileResponse.getSourceId().equals(sort.getResourceId())) {
                        StudyCourseFileResponse response = new StudyCourseFileResponse();
                        response.setCourseFileId(studySourceFileResponse.getSourceId());
                        response.setName(studySourceFileResponse.getName());
                        response.setCreatedAt(studySourceFileResponse.getCreatedAt());
                        response.setFilePath(studySourceFileResponse.getSourcePath());
                        response.setSortOrder(sort.getSortOrder());
                        responseList.add(response);
                    }
                }

                StudyWebSourse webSourse = studyWebSourseMapper.selectById(sort.getResourceId());
                if (webSourse != null) {
                    StudyCourseFileResponse response = new StudyCourseFileResponse();
                    response.setCourseFileId(webSourse.getWebId());
                    response.setName(webSourse.getWebName());
                    response.setCreatedAt(webSourse.getUploadedAt());
                    response.setFilePath(webSourse.getWebSoursePath());
                    response.setTag("网页资源");

                    StudyResourceSort webSort = sortList.stream()
                            .filter(s -> s != null && s.getResourceId() != null && s.getResourceId().equals(webSourse.getWebId()) && "web".equals(s.getResourceType()))
                            .findFirst()
                            .orElse(null);

                    response.setSortOrder(webSort != null ? webSort.getSortOrder() : 0);
                    responseList.add(response);
                }
            }
        }

        if (sentence != null && !sentence.isEmpty()) {
            responseList = responseList.stream()
                    .filter(response -> response.getName().contains(sentence))
                    .collect(Collectors.toList());
        }

        return responseList;
    }




    @Override
    public List<StudyCourseFileResponse> getUserCourseByuserId(String userId,String sentence) {
        // 获取用户有关的所有课程信息
        List<StudyTeacherCourse> courses = studyTeacherCourseMapper.getCourseByteacherId(userId);

        List<StudyCourseFileResponse> courseFile = new ArrayList<>();
        for (StudyTeacherCourse course : courses) {
            //课程不包含文件夹时该目录已经存在异常，不显示
            if (course.getFolderId()!=null){
                StudyCourseFile folder =  studyCourseFileMapper.getCourseFileById(course.getFolderId());
            if (folder!=null) {
                if (!"知识空间".equals(course.getCourseTag())) {
                    StudyCourseFileResponse response = new StudyCourseFileResponse();
                    response.setCourseId(course.getCourseId());
                    response.setCourseFileId(course.getFolderId());
                    response.setName(folder.getName());
                    response.setCreatedAt(folder.getCreatedAt());
                    response.setFilePath(folder.getFilePath());
                    response.setLevel(folder.getLevel());
                    response.setTag(course.getCourseTag());
                    response.setChildId(folder.getChildId());
                    String fileUrl = ossService.getFileUrl(course.getCourseImage());
                    response.setCourseImageUrl(fileUrl);
//            response.setTag(folder.ge);
                    courseFile.add(response);
                }
            }
            }else {
                //视为课程未被删除，状态异常，执行删除课程
                studyTeacherCourseMapper.delete(new QueryWrapper<StudyTeacherCourse>().eq("course_id",course.getCourseId()));
            }
        }
        if (sentence != null && !sentence.isEmpty()) {
            courseFile = courseFile.stream()
                    .filter(response -> response.getName().contains(sentence))
                    .collect(Collectors.toList());
        }
        return courseFile;
    }



    @Override
    public List<StudyCourseFileResponse> getUserCourseResourceTree(String userId) {
        // 获取用户有关的所有课程信息
        List<StudyTeacherCourse> courses = studyTeacherCourseMapper.getCourseByteacherId(userId);

        List<StudyCourseFileResponse> courseResourceTrees = new ArrayList<>();

        for (StudyTeacherCourse course : courses) {
            // 获取课程对应的根文件夹
            StudyCourseFileResponse rootFolder = buildFileTree(course.getFolderId());

            // 设置课程信息到根文件夹
            if (rootFolder != null) {
                rootFolder.setTag(course.getCourseTag());
                courseResourceTrees.add(rootFolder);
            }
        }
        return courseResourceTrees;
    }

    public StudyCourseFileResponse getCourseTree(String userId, Long courseId){
        StudyTeacherCourse course = studyTeacherCourseMapper.getCourseById(courseId);
        if(course != null)
        {
            StudyCourseFileResponse rootFolder = buildFileTree(course.getFolderId());
            return rootFolder;
        }

        return null;
    }


    private StudyCourseFileResponse buildFileTree(Long folderId) {
        // 获取当前文件夹的信息
        StudyCourseFile folder =  studyCourseFileMapper.getCourseFileById(folderId);

        if (folder == null) {
            return null;
        }
        StudyCourseFileResponse folderResponse = new StudyCourseFileResponse();
        folderResponse.setCourseFileId(folder.getCourseFileId());
        folderResponse.setName(folder.getName());
        folderResponse.setParentId(folder.getParentId());
        folderResponse.setFilePath(folder.getFilePath());
        folderResponse.setCreatedAt(folder.getCreatedAt());
        folderResponse.setChildId(folder.getChildId());
        folderResponse.setCourseId(folder.getCourseId());

        // 获取子文件夹并递归构建子文件夹的响应
        List<StudyCourseFile> childFiles = studyCourseFileMapper.getFilesByParentId(folderId);
        //获取对应资源（文档和音视频）
        List<StudySourceFileResponse> studySourceFileResponses = getSourseFiles(folderId,"");
        folderResponse.setSourceFiles(studySourceFileResponses);

        //获取网页资源
        List<StudyWebSourse> webSourse = studyWebSourseMapper.getWebByCourseFileId(folderId);
        folderResponse.setWebSourses(webSourse);

        for (StudyCourseFile child : childFiles) {
            StudyCourseFileResponse childResponse = buildFileTree(child.getCourseFileId());
            if (childResponse != null) {
                folderResponse.getChildFiles().add(childResponse);
            }
        }

        return folderResponse;

    }

    @Override
    public List<StudySourceFileResponse> getSourseFiles(Long courseFileId,String sentence) {
        // 从三个资源表中获取在courseFileId下的那些资源
        List<StudySourceFileResponse> responseList = new ArrayList<>();
        // study_filesource
        List<StudyFileSource> studyFileSources = studyFileSourceMapper.selectList(new QueryWrapper<StudyFileSource>().eq("file_id", courseFileId));
        // 将 study_filesource 表中的资源转换为 StudySourceFileResponse
        for (StudyFileSource studyFileSource : studyFileSources) {
            StudySourceFileResponse response = new StudySourceFileResponse();
            response.setSourceId(studyFileSource.getFilesourceId());
            response.setCourseId(studyFileSource.getCourseId());
            response.setName(studyFileSource.getFileName());
            response.setSourcePath(studyFileSource.getFilesourcePath());
            response.setCreatedAt(studyFileSource.getCreatedAt());
            response.setTag("文档"); // 假设是文档类型的资源
            response.setOssWriteStatus(studyFileSource.getOssWriteStatus());
            response.setRagCompleteStatus(studyFileSource.getRagCompleteStatus());
            response.setSmartTextStatus(studyFileSource.getSmartTextStatus());
            response.setHandleCompleteStatus(studyFileSource.getHandleCompleteStatus());
            responseList.add(response);
        }

        // 从 coursesource 表中获取在 courseFileId 下的资源
        List<CourseSource> courseSources = courseSourceMapper.selectList(
                new QueryWrapper<CourseSource>().eq("file_id", courseFileId)
        );

        // 将 coursesource 表中的资源转换为 StudySourceFileResponse
        for (CourseSource courseSource : courseSources) {
            // 判断已上传未加工完的音视频资源的状态
//            if (!courseSource.getTranscriptionComplete() && courseSource.getOssWriteStatus()) {
//                String taskId = courseSource.getTaskId();
//                if (taskId != null && !taskId.isEmpty()) {
//                    Jugehandlevideostate(courseSource.getTaskId());
//                }
//            }
            StudySourceFileResponse response = new StudySourceFileResponse();
            response.setCourseId(courseSource.getCourseId());
            response.setSourceId(courseSource.getCourseSourceId());
            response.setName(courseSource.getFileName()); // 这里使用 language 字段作为名称，按需修改
            response.setSourcePath(courseSource.getFilesourcePath()); // 假设有一个路径，如果没有可以忽略
            response.setCreatedAt(courseSource.getCreatedAt());
            response.setTag("音视频"); // 假设是音视频类型的资源
            response.setOssWriteStatus(courseSource.getOssWriteStatus());
            response.setTranscriptionComplete(courseSource.getTranscriptionComplete());
            response.setTranscriptionCompleteStatus(courseSource.getTranscriptionCompleteStatus());
            responseList.add(response);
        }
        //依据sentence对 List<StudySourceFileResponse>中的Name进行过滤
        if (sentence != null && !sentence.isEmpty()) {
            responseList = responseList.stream()
                    .filter(response -> response.getName().contains(sentence))
                    .collect(Collectors.toList());
        }

        return responseList;
    }

    public List<StudySourceFileResponse> getSourseFilesBycourseId(Long courseId) {
        //从三个资源表中获取在courseFileId下的那些资源
        List<StudySourceFileResponse> responseList = new ArrayList<>();
        //study_filesource
        List<StudyFileSource> studyFileSources = studyFileSourceMapper.selectList(new QueryWrapper<StudyFileSource>().eq("course_id", courseId));
        // 将 study_filesource 表中的资源转换为 StudySourceFileResponse
        for (StudyFileSource studyFileSource : studyFileSources) {
            StudySourceFileResponse response = new StudySourceFileResponse();
            response.setSourceId(studyFileSource.getFilesourceId());
            response.setCourseId(studyFileSource.getCourseId());
            response.setName(studyFileSource.getFileName());
            response.setSourcePath(studyFileSource.getFilesourcePath());
            response.setCreatedAt(studyFileSource.getCreatedAt());
            response.setTag("文档"); // 假设是文档类型的资源
            response.setOssWriteStatus(studyFileSource.getOssWriteStatus());
            response.setRagCompleteStatus(studyFileSource.getRagCompleteStatus());
            response.setSmartTextStatus(studyFileSource.getSmartTextStatus());
            response.setHandleCompleteStatus(studyFileSource.getHandleCompleteStatus());
            responseList.add(response);
        }
        // 从 coursesource 表中获取在 courseFileId 下的资源
        List<CourseSource> courseSources = courseSourceMapper.selectList(
                new QueryWrapper<CourseSource>().eq("course_id", courseId)
        );

        // 将 coursesource 表中的资源转换为 StudySourceFileResponse
        for (CourseSource courseSource : courseSources) {
            // 判断已上传未加工完的音视频资源的状态
//            if (!courseSource.getTranscriptionComplete() && courseSource.getOssWriteStatus()) {
//                String taskId = courseSource.getTaskId();
//                if (taskId != null && !taskId.isEmpty() ) {
//                    Jugehandlevideostate(courseSource.getTaskId());
//                }
//            }
            StudySourceFileResponse response = new StudySourceFileResponse();
            response.setCourseId(courseSource.getCourseId());
            response.setSourceId(courseSource.getCourseSourceId());
            response.setName(courseSource.getFileName()); // 这里使用 language 字段作为名称，按需修改
            response.setSourcePath(courseSource.getFilesourcePath()); // 假设有一个路径，如果没有可以忽略
            response.setCreatedAt(courseSource.getCreatedAt());
            response.setTag("音视频"); // 假设是音视频类型的资源
            response.setOssWriteStatus(courseSource.getOssWriteStatus());
            response.setTranscriptionComplete(courseSource.getTranscriptionComplete());
            response.setTranscriptionCompleteStatus(courseSource.getTranscriptionCompleteStatus());
            responseList.add(response);
        }

        return responseList;
    }
    @Override
    public List<StudySourceFileResponse> getSourseFilesALL(String userId,String sentence) {
        //从三个资源表中获取在courseFileId下的那些资源
        List<StudySourceFileResponse> responseList = new ArrayList<>();

        List<StudyTeacherCourse> courses = studyTeacherCourseMapper.getCourseByteacherId(userId);
        for (StudyTeacherCourse course : courses) {
            responseList.addAll(getSourseFilesBycourseId(course.getCourseId()));
        }
        if (sentence != null && !sentence.isEmpty()) {
            responseList = responseList.stream()
                    .filter(response -> response.getName().contains(sentence))
                    .collect(Collectors.toList());
        }
        return responseList;
    }

    @Override//返回当前记录的时长
    public int updateUserCourseStudyRecord(Long courseId, String userId, Integer time,
        boolean isStudyStart) {
        //基于userId和courseId查询学习记录
        UserCourseStudyRecord record = userCourseStudyRecordMapper.selectOne(new LambdaQueryWrapper<UserCourseStudyRecord>()
                .eq(UserCourseStudyRecord::getUserId, userId)
                .eq(UserCourseStudyRecord::getCoursesourceId, courseId));
        //无则插入
        if (record == null) {
            UserCourseStudyRecord newRecord = new UserCourseStudyRecord();
            newRecord.setUserId(userId);
            newRecord.setCoursesourceId(courseId);
            newRecord.setStudyCount(1);
            newRecord.setStudyDuration(time);
            if (userCourseStudyRecordMapper.insert(newRecord) > 0){
                //插入成功返回，更新后的时长
                return newRecord.getStudyDuration();
            }else return 0;//未插入成功，未记录
        }else {
            //有则更新
            if (isStudyStart) {
                record.setStudyCount(record.getStudyCount()+1);
            }
            record.setStudyDuration(record.getStudyDuration()+time);
            if (userCourseStudyRecordMapper.update(record, new LambdaQueryWrapper<UserCourseStudyRecord>()
                    .eq(UserCourseStudyRecord::getUserId, userId)
                    .eq(UserCourseStudyRecord::getCoursesourceId, courseId)) > 0){
                return record.getStudyDuration();//返回数据库中记录的时间
            }else {
                return record.getStudyDuration()-time;
            }

        }
    }

    @Override
    public CourserReviewResponse getCourseReview(String coursesTag, String userId) {
        CourserReviewResponse courserReviewResponse = new CourserReviewResponse();
        //1.获取个人空间信息，如果所有字段都不为null则isUserMetaComplete为true否则为false
        // 调用 Feign 客户端获取用户元数据
        R response = userServiceClient.getUserMeta();
        // 将整数R.code变为httpstatus code
        HttpStatus httpStatus = HttpStatus.valueOf(response.getCode());
        if (!httpStatus.is2xxSuccessful()){
            log.error("获取回放课程时,获取用户元数据失败");
            return null;
        }
//        UserAuthenticationResponse userMetaResponse = (UserAuthenticationResponse) response.getData();
        // 使用 ObjectMapper 进行类型转换
        ObjectMapper objectMapper = new ObjectMapper();
        UserAuthenticationResponse userMetaResponse = objectMapper.convertValue(response.getData(), UserAuthenticationResponse.class);

        //判断所有字段
        courserReviewResponse.setIsUserMetaComplete(areAllFieldsNotNull(userMetaResponse));
        //获取用户基本信息
        //  通过ID获取用户实体
        R whoami = userServiceClient.whoami(userId);

        // 判断返回是否正确
        HttpStatus status = HttpStatus.valueOf(whoami.getCode());
        if (!status.is2xxSuccessful()) {
            log.error(String.format("获取用户信息失败，用户ID: %s", userId));
        }

        // Bean类型转换
        User userDetail = BeanUtils.copyBean(whoami.getData(), User.class);

        //2.获取课程列表:课程学习状态
        List<StudyTeacherCourse>courses=studyTeacherCourseMapper.selectList(new LambdaQueryWrapper<StudyTeacherCourse>().eq(StudyTeacherCourse::getCourseTag,coursesTag));
        List<CourseResponse> courseResponseList = courses.stream().map(
            course -> {
                CourseResponse courseResponse = new CourseResponse();
                courseResponse.setCourseId(course.getCourseId());
                courseResponse.setTeacherId(course.getTeacherId());
                courseResponse.setFolderId(course.getFolderId());

                courseResponse.setCourseName(course.getCourseName());
                courseResponse.setCourseTag(course.getCourseTag());
                courseResponse.setCourseDescription(course.getCourseDescription());
                //获取封面
                courseResponse.setCourseImage(course.getCourseImage() != null
                    ? ossService.getFileUrl(course.getCourseImage())
                    : null);
                //每个依次判断课程学习完成状态,对每个视频做判断

                //NOTE: 轮询更新其他方式下的用户学习状态
               if (!offLineExportService.syncCourseStudyStatus(userDetail,
                   String.valueOf(course.getCourseId()))){
                   log.error("用户"+userId+"同步其他方式课程学习状态时失败："+course.getCourseId());
               }
                //先查看课程状态记录
                courseResponse.setIscourseComplete(isCourseCompleteEnd(course.getCourseId(), userId));
                // 记录回放学习记录
//                UserCourseStudyRecord userCourseStudyRecord= userCourseStudyRecordMapper.selectOne(new LambdaQueryWrapper<UserCourseStudyRecord>()
//                        .eq(UserCourseStudyRecord::getCoursesourceId, courseSource.getCourseSourceId()).eq(UserCourseStudyRecord::getUserId, userId)
//                        .last("limit 1"));
//                courseResponse.setCourseRrecordTime();

                // 获取其他方式的学习状态
                LambdaQueryWrapper<OfflineExport> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(OfflineExport::getSchoolId, userDetail.getSchoolId())
                        .eq(OfflineExport::getCourseId, course.getCourseId())
                        .eq(OfflineExport::getRealname, userDetail.getRealname())
                        .eq(OfflineExport::getIsSync, 1)
                        .last("limit 1");
                OfflineExport offlineExport = offlineExportMapper.selectOne(queryWrapper);
                courseResponse.setOtherComplete(offlineExport != null);
                //获取课程的回放学习时长
                //由于前面的课程状态查询中函盖逻辑判断，其他学习方式学习过就不会查询回放时长，因此这里统计时长时重新查询
                List<CourseSource> courseSources= courseSourceMapper.selectList(new LambdaQueryWrapper<CourseSource>().eq(CourseSource::getCourseId, course.getCourseId()));
                int courseDuration=0;
                for (CourseSource courseSource : courseSources) {
                    //获取学习时长
                    UserCourseStudyRecord userCourseStudyRecord= userCourseStudyRecordMapper.selectOne(new LambdaQueryWrapper<UserCourseStudyRecord>().eq(UserCourseStudyRecord::getCoursesourceId, courseSource.getCourseSourceId()).eq(UserCourseStudyRecord::getUserId, userId)
                            .last("limit 1"));
                    if (userCourseStudyRecord==null){
                        courseDuration +=0;
                    }else {
                    courseDuration += userCourseStudyRecord.getStudyDuration();
                    }
                }
                courseResponse.setCoursePlatformTime(courseDuration);


                return courseResponse;
            }).collect(Collectors.toList());

        courserReviewResponse.setCourses(courseResponseList);
        return courserReviewResponse;
    }

    //判断用户学习状态的最终函数
    public int isCourseCompleteEnd(Long courseId, String userId) {
        //先查看课程状态记录
        UserCourseStudyStatus userCourseStudyStatus = userCourseStudyStatusMapper.selectOne(new LambdaQueryWrapper<UserCourseStudyStatus>()
            .eq(UserCourseStudyStatus::getUserId, userId).eq(UserCourseStudyStatus::getCourseId,courseId).last("limit 1"));
        if (userCourseStudyStatus == null || userCourseStudyStatus.getUserStudyStatus()!=COMPLETED) {
            //当其他方式目前没有学习完，去判断平台是否学习完
            int study_status = isCourseComplete(courseId, userId);
            if (study_status == 2) {
                if (userCourseStudyStatus == null){
                    userCourseStudyStatus = new UserCourseStudyStatus();
                    userCourseStudyStatus.setUserId(userId);
                    userCourseStudyStatus.setCourseId(courseId);
                    userCourseStudyStatus.setUserStudyStatus(COMPLETED);
                    userCourseStudyStatusMapper.insert(userCourseStudyStatus);
                }else {
                    //学习完成，更新状态为2
                    userCourseStudyStatus.setUserStudyStatus(COMPLETED);
                    userCourseStudyStatusMapper.update(userCourseStudyStatus,new LambdaQueryWrapper<UserCourseStudyStatus>()
                        .eq(UserCourseStudyStatus::getUserId, userId).eq(UserCourseStudyStatus::getCourseId,courseId));
                }
            }
            return study_status;
//            courseResponse.setIscourseComplete(study_status);
        }else {//实际应该是只有2 即学习完成
            return userCourseStudyStatus.getUserStudyStatus().ordinal();
//            courseResponse.setIscourseComplete(userCourseStudyStatus.getUserStudyStatus());
        }

    }


    @Override
    public List<TrainingCampListResponse> getTrainingCampList(String sentence) {
        //对标签和名称模糊查询
        List<TrainingCamp> trainingCampList = trainingCampMapper.selectList(new LambdaQueryWrapper<TrainingCamp>(
           ).like(TrainingCamp::getTags,sentence).or().like(TrainingCamp::getCampName,sentence));

        return trainingCampList.stream().map(trainingCamp -> {
            TrainingCampListResponse response = new TrainingCampListResponse();
            response.setCampId(trainingCamp.getCampId());
            response.setCampName(trainingCamp.getCampName());
            response.setOrganizerInfo(trainingCamp.getOrganizerInfo());
            response.setCoverImage(trainingCamp.getCoverImagePath() != null
                ? ossService.getFileUrl(trainingCamp.getCoverImagePath())
                : null);
            response.setTags(trainingCamp.getTags());
            response.setStartTime(trainingCamp.getStartTime());
            response.setEndTime(trainingCamp.getEndTime());
            return response;
        }).collect(Collectors.toList());
    }

    @Override
    public boolean createTrainingCamp(TrainingCamp trainingCamp, MultipartFile trainingCampImage) {
        SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(3, 1);
        // 获取原始文件名
        String originalFilename = trainingCampImage.getOriginalFilename();

        // 获取文件扩展名
        String fileExtension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        } else {
            log.error("文件解析扩展名出现错误：" + originalFilename);
            return false;
        }
        Long id =idGenerator.nextId();
        boolean uploadImage = ossService.uploadFile(trainingCampImage, "image/TrainingCamp/",
            id + fileExtension);
        if (!uploadImage){
            log.info("上传训练营图片失败"+trainingCamp.getCampName());
            return false;
        }else {
            trainingCamp.setCoverImagePath("image/TrainingCamp/"+id + fileExtension);
            return trainingCampMapper.insert(trainingCamp) > 0;
        }
    }

    @Override
    public List<TrainingCampListResponse> getTrainingCampListBytag(String coursesTag) {
        //对标签和名称模糊查询
        List<TrainingCamp> trainingCampList = trainingCampMapper.selectList(new LambdaQueryWrapper<TrainingCamp>(
        ).eq(TrainingCamp::getTags,coursesTag));

        return trainingCampList.stream().map(trainingCamp -> {
            TrainingCampListResponse response = new TrainingCampListResponse();
            response.setCampId(trainingCamp.getCampId());
            response.setCampName(trainingCamp.getCampName());
            response.setOrganizerInfo(trainingCamp.getOrganizerInfo());
            response.setCoverImage(trainingCamp.getCoverImagePath() != null
                    ? ossService.getFileUrl(trainingCamp.getCoverImagePath())
                    : null);
            response.setTags(trainingCamp.getTags());
            response.setStartTime(trainingCamp.getStartTime());
            response.setEndTime(trainingCamp.getEndTime());
            return response;
        }).collect(Collectors.toList());
    }

    //用于判断用户是否学完课程内的所有视频
    private int isCourseComplete(Long courseId, String userId) {
        // 获取该课程下的所有音视频文件
        List<CourseSource> courseSources= courseSourceMapper.selectList(new LambdaQueryWrapper<CourseSource>().eq(CourseSource::getCourseId, courseId));
        //获取每个音视频对应的学习时长要求,当音视频和学习记录都能一次性读取时（观看记录表，没有courseID字段关联，该方法不采用）
//        Map<Long, Integer> studyTimeRequirements = courseSources.stream()
//            .collect(Collectors.toMap(CourseSource::getCourseSourceId, CourseSource::getStudyTimeRequirement));
//        int courseSourceNum=courseSources.size();

        List<Integer> CourseCompleteList = new ArrayList<>();
        //获取用户已有的学习记录
        for (CourseSource courseSource : courseSources){
            UserCourseStudyRecord userCourseStudyRecord= userCourseStudyRecordMapper.selectOne(new LambdaQueryWrapper<UserCourseStudyRecord>().eq(UserCourseStudyRecord::getCoursesourceId, courseSource.getCourseSourceId()).eq(UserCourseStudyRecord::getUserId, userId)
                .last("limit 1"));
            if (userCourseStudyRecord==null){
                CourseCompleteList.add(0);
            }else {
                //如果现有记录已经完成了,可能外部导入过其他途径已经学习完成了
                if (userCourseStudyRecord.getUserStudyStatus()==1){
//                    note: 2表示该视频已完成
                    CourseCompleteList.add(2);
                }else{
                    //什么途径都还没学完，这时候就需要根据最新的学习时间去判断
                    if(userCourseStudyRecord.getStudyDuration()>0){
                        if(userCourseStudyRecord.getStudyDuration()>=courseSource.getStudyTimeRequirement()){
                            //更新学习状态为已完成
                            userCourseStudyRecord.setUserStudyStatus(1);
                            userCourseStudyRecordMapper.update(userCourseStudyRecord, new LambdaQueryWrapper<UserCourseStudyRecord>().eq(UserCourseStudyRecord::getCoursesourceId, userCourseStudyRecord.getCoursesourceId()).eq(UserCourseStudyRecord::getUserId, userCourseStudyRecord.getUserId()));

                            CourseCompleteList.add(2);
                        }else {
//                            note:1表示该视频正在学习
                            CourseCompleteList.add(1);
                        }
                    }
                    else {
//                        note:0表示该视频未学习
                        CourseCompleteList.add(0);
                    }
                }
//                if (userCourseStudyRecord.getStudyDuration()>=courseSource.getStudyTimeRequirement()){
//                    if (userCourseStudyRecord.getUserStudyStatus()!=1){
//                        //更新学习状态为已完成
//                        userCourseStudyRecord.setUserStudyStatus(1);
//                        userCourseStudyRecordMapper.update(userCourseStudyRecord, new LambdaQueryWrapper<UserCourseStudyRecord>().eq(UserCourseStudyRecord::getCoursesourceId, userCourseStudyRecord.getCoursesourceId()));
//                    }
//                    CourseCompleteList.add(1);
//                }else {
//                    CourseCompleteList.add(0);
//                }
            }
        }
        // 遍历列表，判断是否已经完成学习
        int sum = CourseCompleteList.stream().mapToInt(Integer::intValue).sum();
        int size = CourseCompleteList.size();

        return (sum == 0) ? 0 : (sum < 2*size) ? 1 : 2;

    }
    private  boolean areAllFieldsNotNull(UserAuthenticationResponse response) {
        return response != null &&
            response.getRealName() != null &&
            response.getSchool() != null &&
            response.getCollege() != null &&
            response.getMajor() != null &&
            response.getStudentId() != null &&
            response.getPhoneNumber() != null &&
            response.getEmail() != null &&
            response.getParticipationType() != null &&
            response.getCampus() != null &&
            response.getStudentStatus() != null &&
            response.getEnrollmentYear() != null &&
            response.getProjectStatus() != null &&
            response.getProjectType() != null &&
            response.getProjectName() != null;
    }
    @Override
    public int hasKnowledgeSpace() {
        String userId = UserContext.getUserId();
        String tag = "知识空间";
        return studyTeacherCourseMapper.countByTagAndId(userId, tag);
    }
    @Override
    public String getKnowledgeSpaceId(){
        String userId = UserContext.getUserId();
        return studyTeacherCourseMapper.getKnowledgeSpaceId(userId);
    }

    @Override
    public String getRootFolderId(String courseId){
        return studyCourseFileMapper.getRootFolderId(courseId);
    }
}


